package com.espirit.eap.manager;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.springframework.stereotype.Service;

import com.espirit.eap.sa.Employee;
import com.espirit.eap.sa.EmployeeService;
import com.espirit.eap.sa.User;
import com.espirit.eap.util.StatGenericJPAService;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.spring.Executor;
import com.googlecode.cswish.util.OgnlExUtil;

@Service
public class ModelExportMappingService {

	@Resource
	DepartmentService departmentService;
	
	@Resource
	EmployeeService employeeService;
	
	private final static Object NULL = new Object();
	
	@PersistenceContext(unitName="espirit")
	protected EntityManager em;
	
	private Map<String, String> modelMapping = new HashMap<String, String>();
	
	@Resource
	private OgnlExUtil ognlUtil;
	
	@Resource
	private StatGenericJPAService genericService;
	
	@PostConstruct
	private void init() {
//		modelMapping.put("party", Party.class.getName());
		modelMapping.put("createdBy", User.class.getName());
		modelMapping.put("department", Department.class.getName());
		modelMapping.put("employee", Employee.class.getName());
	}
	
	public void registerExportModeMapping() {
		genericService.registerModeMapping(new Executor<Object, Object[]>() {
			@Override
			public Object execute(Object[] parameters) {
				return getModelByName((EapImport)parameters[0], (Map<String, Map<Object, Object>>)parameters[1],
						(String)parameters[2], parameters[3]);
			}
		});
	}
	
	private Object getModelByName(EapImport eapImport, Map<String, Map<Object, Object>> cache, String property, Object value) {
		int pos = property.indexOf(".");
		if (pos > 0){
			property = property.substring(pos + 1, property.length());
		}
		String mappingProperty = modelMapping.get(property);
		
		if (mappingProperty == null) {
			return null;
		}
		Map<Object, Object> modelCache = cache.get(property);
		if (modelCache != null) {
			Object model = modelCache.get(value);
			if (model != null) {
				return model == NULL ? null : model;
			}
		} else {
			modelCache = new HashMap<Object, Object>();
			cache.put(property, modelCache);
		}
		
		Object model = null;
		FlushMode oldMode = getSession().getFlushMode();
		getSession().setFlushMode(FlushMode.MANUAL);

		String strValue = (String)ognlUtil.getXWorkConverter().convertValue(value, String.class);
		if (mappingProperty.equals(User.class.getName())){
			String ql = " from " + mappingProperty + " a where a.code=?";
			User user = (User) genericService.searchByQl(new QLInfo(ql, true, value), false).getData(0);
			
			if (user == null){
				model = new User();
				((User)model).setCode(strValue);
				((User)model).setName(strValue);
				model = genericService.add(model);
			}
		}  else if (mappingProperty.equals(Department.class.getName())){
			String id =  departmentService.getDeptIdByName(strValue);
			if (id != null){
				return genericService.load(Department.class, id);
			} else {
				return null;
			}
		} else if (mappingProperty.equals(Employee.class.getName())){
			Employee emp = employeeService.getEmployeeByName(strValue);
			return emp;
		} else {
			String ql = " from " + mappingProperty + " a where a.name=? or a.code=?";
			PageInfo pageInfo = genericService.searchByQl(new QLInfo(ql, true, strValue, strValue), false);
			model = pageInfo.getData(0);
			
		}
		getSession().setFlushMode(oldMode);
		if (model == null) {
			modelCache.put(value, NULL);
		} else {
			modelCache.put(value, model);
		}
		return model;
	}
	
	public Session getSession(){
		return (Session)em.getDelegate();
	}
}
